<?php
/**
 * 数据记录集
 *
 * @package if
 * @subpackage module.activerecord
 * @since 1.0
 */
class IDbPartitionRecordSet extends IMagicObject implements IIterable,Countable {
	private $records = array();
	/**
	 * Enter description here...
	 *
	 * @var IDbPartitionDAO
	 */
	private $dao;
	
	/**
	 * Enter description here...
	 *
	 * @var IDbPartitionQuery
	 * @since 1.0.2
	 */
	private $query;
	
	/**
	 * 构造
	 *
	 * @param IDbPartitionDAO $dao DAO对象
	 * @since 1.0
	 */
	function __construct($dao) {
		$this->dao = $dao;
	}
	
	/**
	 * 取得第一条记录
	 *
	 * @return IDbPartitionRecord
	 * @since 1.0
	 */
	function first() {
		return $this->record(0);
	}
	
	/**
	 * 取得最后一条记录
	 *
	 * @return IDbPartitionRecord
	 * @since 1.0
	 */
	function last() {
		$records = $this->records;
		if (empty($records)) {
			return null;
		}
		$record = array_pop($records);
		if (!if_is_instance_of($record, "IDbPartitionRecord")) {
			$record = $this->dao->create($record);
		}
		return $record;
	}
	
	/**
	 * 删除当前记录集
	 * 
	 * 返回影响的行数
	 *
	 * @param boolean $deep 是否深度删除
	 * @return integer
	 * @since 1.0
	 */
	function delete($deep = false) {
		$count = 0;
		foreach ($this->records as $record) {
			if (if_is_instance_of($record, "IDbPartitionRecord")) {
				$count += $record->delete($deep);
			}
			else if (is_array($record)) {
				$record = $this->dao->create($record);
				$count += $record->delete($deep);
			}
		}
		return $count;
	}
	
	/**
	 * 移除一个记录
	 *
	 * @param integer $index 记录的索引
	 * @since 1.0
	 */
	function remove($index) {
		if (isset($this->records[$index])) {
			unset($this->records[$index]);
		}
	}
	
	/**
	 * 添加一条记录
	 *
	 * @param array|IDbPartitionRecord $record 记录
	 * @since 1.0
	 */
	function add($record) {
		$this->records[] = $record;
	}
	
	/**
	 * 取得某个记录
	 *
	 * @param integer $index 索引
	 * @return IDbPartitionRecord
	 * @since 1.0
	 */
	function record($index) {
		if (!isset($this->records[$index])) {
			return null;
		}
		$record = $this->records[$index];
		$original = null;
		if (!if_is_instance_of($record, "IDbPartitionRecord")) {
			$original = $record;
			$record = $this->dao->create($record);
		}
		else {
			$original = $record->attrs();
		}
		$this->dao->autofill($record, "read");
		$record->_before_read();
		$record->setOriginal($original);
		$record->setAction("read");
		$record->setSaved(true);
		$record->setQuery($this->query);
		$record->_after_read();
		return $record;
	}
	
	/**
	 * 转换为数组形式
	 *
	 * @return array
	 * @since 1.0
	 */
	function arrays() {
		$records = $this->records;
		foreach ($records as $key => $record) {
			if (if_is_instance_of($record, "IDbPartitionRecord")) {
				$records[$key] = $record->attrs();
			}
		}
		return $records;
	}
	
	/**
	 * 取得所有记录，以Array<IDbPartitionRecord>形式返回
	 *
	 * @return array
	 * @since 1.0
	 */
	function records() {
		$records = $this->records;
		foreach ($records as $key => $record) {
			if (!if_is_instance_of($record, "IDbPartitionRecord")) {
				$records[$key] = $this->dao->create($record);
			}
		}
		return $records;
	}
	
	/**
	 * 设置记录
	 * 
	 * 从1.0.3开始，新的记录集将覆盖老的记录集，而不是以前版本中的叠加。
	 * 
	 * 如果想叠加到以前的记录集上，可以使用addAll()方法
	 *
	 * @param array $records 记录
	 * @since 1.0
	 */
	function setRecords(array $records = null) {
		if (!$records) {
			$this->records = array();
			return;
		}
		$this->records = $records;
	}
	
	/**
	 * 添加一个新的记录集
	 *
	 * @param array $records 记录集
	 * @since 1.0.3
	 */
	function addAll(array $records) {
		$this->records = if_array_join($this->records, $records);
	}
	
	/**
	 * 计算记录数
	 *
	 * @return integer
	 * @since 1.0
	 */
	function count() {
		return count($this->records);
	}
	
	/**
	 * 将当前对象转换为数组
	 *
	 * @return array
	 * @since 1.0
	 */
	function asArray() {
		return $this->records();
	}
	
	/**
	 * 取得迭代器
	 *
	 * @return IListIterator
	 * @since 1.0
	 */
	function getIterator() {
		$records = $this->records();
		return new IListIterator($records);
	}
	
	/**
	 * 判断一个偏移量是否存在
	 *
	 * 实现了 ArrayAccess 接口对应方法
	 * 
	 * @param integer $index
	 * @return boolean
	 */
	function offsetExists($index) {
		return array_key_exists($index, $this->records);
	}
	
	/**
	 * 从一个偏移量中取得数据
	 * 
	 * 实现了 ArrayAccess 接口对应方法
	 *
	 * @param integer $index 偏移量
	 * @return mixed
	 */
	function offsetGet($index) {
		return $this->record($index);
	}
	
	/**
	 * 设置偏移量位置上的值
	 *
	 * 实现了 ArrayAccess 接口对应方法
	 * 
	 * @param integer $index 偏移量
	 * @param mixed $item 值
	 */
	function offsetSet($index, $item) {
		$this->records[$index] = $item;
	}
	
	/**
	 * 删除偏移量位置对应的元素
	 * 
	 * 实现了 ArrayAccess 接口对应方法
	 *
	 * @param integer $index 偏移量
	 */
	function offsetUnset($index) {
		$this->remove($index);
	}	
	
	function sum($attr) {
		$sum = 0;
		foreach ($this->records as $record) {
			if (if_is_instance_of($record, "IDbPartitionRecord")) {
				$record = $record->asArray();
			}
			if (isset($record[$attr])) {
				$sum += $record[$attr];
			}
		}
		return $sum;
	}
	
	function avg($attr, $decimal = 0) {
		$count = $this->count();
		if ($count == 0) {
			return 0;
		}
		return round($this->sum($attr)/$count, $decimal);
	}
	
	function asc($attr) {
		$this->_order_attr = $attr;
		$this->_order_method = "asc";
		$records = $this->records;
		usort($records, array($this, "_sortCallback"));
		$set = new IDbPartitionRecordSet($this->dao);
		$set->setRecords($records);
		return $set;
	}
	
	function desc($attr) {
		$this->_order_attr = $attr;
		$this->_order_method = "desc";
		$records = $this->records;
		usort($records, array($this, "_sortCallback"));
		$set = new IDbPartitionRecordSet($this->dao);
		$set->setRecords($records);
		return $set;
	}
	
	private function _sortCallback($record1, $record2) {
		if ((!is_array($record1) && !if_is_instance_of($record1, "IDbPartitionRecord")) || (!is_array($record2) && !if_is_instance_of($record2, "IDbPartitionRecord"))) {
			return 0;
		}
		if (is_object($record1)) {
			$record1 = $record1->asArray();
		}
		if (is_object($record2)) {
			$record2 = $record2->asArray();
		}
		$attr1 = isset($record1[$this->_order_attr])?$record1[$this->_order_attr]:null;
		$attr2 = isset($record2[$this->_order_attr])?$record2[$this->_order_attr]:null;
		if ($attr1 == $attr2) {
			return 0;
		}
		if ($attr1 > $attr2) {
			return ($this->_order_method == "asc")?1:-1;
		}
		if ($attr1 < $attr2) {
			return ($this->_order_method == "asc")?-1:1;
		}
	}
	
	function max($attr, $fetchAttr = false) {
		$record = $this->desc($attr)->first();
		if ($record) {
			return $fetchAttr?$record->attr($attr):$record;
		}
		return null;
	}
	
	function min($attr, $fetchAttr = false) {
		$record = $this->asc($attr)->first();
		if ($record) {
			return $fetchAttr?$record->attr($attr):$record;
		}
		return null;
	}
	
	/**
	 * 设置关联的查询
	 *
	 * @param IDbPartitionQuery $query 查询
	 * @since 1.0.2
	 */
	function setQuery($query) {
		$this->query = $query;
	}
	
	/**
	 * 重载当前记录集对象
	 *
	 * @return IDbPartitionRecordSet
	 * @since 1.0.3
	 */
	function reload() {
		if ($this->query) {
			$this->setRecords($this->query->findAll());
		}
		return $this;
	}
}

?>